var iframeHtml =
'<?xml version="1.0" encoding="utf-8" ?>'
+'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
+'<html>'
+'<head>'
+'<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
+'</head>'
//+'<script language="javascript">var a = 0;</script>'
+'<body id="ifbody" OnKeyPress="if(event.keyCode==13){event.keyCode=182};'    //;a=0;'
+'return true"'
//+' OnFocus="if(a==0){a=1;alert(\'body : on focus\')};return true"'
+'>'
+'<span>Initial text</span></body>'
+'</html>';

var CMEFrame = Class.create();
CMEFrame.prototype =
{
  initialize: function( wrapperId, id )
  {
    this.wrapper = $( wrapperId );
    this.iframe = Element.extend( this.wrapper.ownerDocument.createElement( 'iframe' ) ); 
    this.iframe.src='javascript:void(0)';
    this.iframe.frameBorder = 0;
    this.iframe.width = '100%';
    this.iframe.height = '100%';
    this.iframe.id = id;
    this.wrapper.appendChild( this.iframe );
    this.doc = this.iframe.contentWindow.document;
    this.doc.open();
    this.doc.write( iframeHtml );
    this.doc.close();
    Event.observe( this.doc, 'contextmenu', this.stub.bindAsEventListener( this ), true );        // IE needs it
    Event.observe( this.doc, 'mousedown', this.doOnMouseDown.bindAsEventListener( this ), true );
    Event.observe( this.doc, 'keypress', this.doOnKeyDown.bindAsEventListener( this ), true );
    Event.observe( this.iframe.contentWindow, 'focus', this.doOnFocus.bindAsEventListener( this ), true );
    this.range = new CRange( this.iframe.contentWindow );
    this.cmenu = globalContextMenu;
    this.palette = globalPalette;
    this.editable = false;
    this.htmlMode = false;
    this.url = '/wcme/engine';     // Servlet URL that process saving and loading content operation
    this.saveBorderStyle = new Hash();
  },
  
  setEditable: function()
  {
    this.editable = true;
//    this.doc.body.bgColor = '#FEFEF8'
    this.saveBorderStyle['border-width'] = this.wrapper.getStyle('border-width');
    this.saveBorderStyle['border-style'] = this.wrapper.getStyle('border-style');
    this.saveBorderStyle['border-color'] = this.wrapper.getStyle('border-color');
    this.wrapper.style.border = '3px double green';

    if( Prototype.Browser.IE )
      this.doc.body.contentEditable = true;
    else
      if( Prototype.Browser.Gecko )
        this.doc.designMode = 'on';
//    var docm = this.doc
//    Try.these
//    (
//      function(){ docm.createRange(); docm.designMode = 'on' },  // FF
//      function(){ docm.body.createTextRange(); docm.body.contentEditable = true }   // IE
//    );
    this.palette.activate( this );
    if( this.htmlMode )
      this.palette.hide();
  },
  
  unsetEditable: function()
  {
    this.editable = false;
//    this.doc.body.bgColor = '#FFFFFF'
    this.wrapper.setStyle( this.saveBorderStyle );

    if( Prototype.Browser.IE )
      this.doc.body.contentEditable = false;
    else
      if( Prototype.Browser.Gecko )
        this.doc.designMode = 'off';
//    var docm = this.doc
//    Try.these
//    (
//      function(){ docm.createRange(); docm.designMode = 'off' },  // FF
//      function(){ docm.body.createTextRange(); docm.body.contentEditable = false }   // IE
//    );
    this.palette.deactivate();
  },
  
  load: function()
  {
//    alert('>>> load');
    new MyAjaxUpdater( this, this.url,
    {
      method: 'get',
      parameters: 
      {
        operation: 'load',
        id: this.iframe.id
      },
      onFailure: function( transport )
      {
        alert('onFailure status= ' + transport.status + ' url=' + this.url );
      }
    });
//    alert('<<< load');
  },
  
  save: function()
  {
    ajaxReq = new Ajax.Request( this.url, 
    {
      method: 'post',
      parameters: 
      {
        operation: 'save',
        content: this.doc.body.innerHTML,
        id: this.iframe.id
      },
    
      onSuccess: function( transport ) 
      {
        alert('Response : ' + transport.responseText );
      },
    
      onFailure: function( transport )
      {
        alert('onFailure status= ' + transport.status + ' url=' + ajaxReq.url );
      }
    });
  },
  
  doOnMouseDown: function( event )
  {
    if( ! Event.isLeftClick( event ) )
    {
      this.cmenu.setMode( this.editable );
      this.cmenu.show( this );
      var pos = Position.cumulativeOffset( this.wrapper ); // this.iframe
//      var pos = Position.realOffset( this.iframe );
//      this.cmenu.menu.style.left = pos[0] + Event.pointerX(event) + "px"
//      this.cmenu.menu.style.top = pos[1] + Event.pointerY(event) + "px"
//      var x = ((Prototype.Browser.IE)?event.x:event.pageX)
//      var y = ((Prototype.Browser.IE)?event.y:event.pageY)
      var x = event.clientX;
      var y = event.clientY;
      this.cmenu.menu.style.left = pos[0] + x + "px"
      this.cmenu.menu.style.top = pos[1] + y + "px"

      Event.stop( event );
      return false;
    }
    else
    {
      this.cmenu.hide();
    }
    return true;
  },
  
  doOnKeyDown: function( event )
  {
    if( ! Prototype.Browser.IE )
      return true;
// IE :
//    alert('key down = ' + keyCode + ' type = {' + event.type + '}' )
    if( event.keyCode == 13 ) // <Enter>
    {
//      alert('Enter key down = ' + keyCode + ' type = {' + event.type + '}' )
      setTimeout( 'if(globalPalette.cmeFrame)globalPalette.cmeFrame.refresh();',100); // IE
    }
    return true;    
  },
  
  doOnFocus: function()
  {
    this.range.isSelected = false;
    this.palette.reset();
    return true;
  },
  
  switchToHTML: function()
  {
    var html = this.doc.body.innerHTML;
    this.doc.body.innerHTML = '';
    this.doc.body.appendChild( this.doc.createTextNode( html ) );
    if( this.editable )
       this.palette.hide();
    this.htmlMode = true;
  },
  
  switchToRichText: function()
  {
    var rText = this.range.getTextFromElement( this.doc.body, null );//this.doc.body.firstChild.nodeValue;
    this.doc.body.innerHTML = rText;
    if( this.editable )
      this.palette.show();
    this.htmlMode = false;
  },
  
  refresh: function()
  {
    if( ! this.htmlMode )
    { // browser mode
      var spanNode = this.doc.body.firstChild;
      while( spanNode != null )
      {
        var subNode = spanNode.firstChild;
        var rText, idx;

        while( subNode != null )
        {
          if( subNode.nodeType == 3 )
          {
            rText = subNode.nodeValue;
            idx = rText.indexOf( String.fromCharCode(182) );
            if( !(idx < 0) )
            {
              if( idx == 0 )
              {
                spanNode.insertBefore( this.doc.createElement( 'br' ), subNode );
                subNode.nodeValue = rText.substring( 1 );
              }  
              else
                if( idx == (rText.length - 1) )  
                {  
                  if( subNode.nextSibling )
                  {
                    spanNode.insertBefore( this.doc.createElement( 'br' ), subNode.nextSibling );
                  }
                  else
                  {
                    spanNode.appendChild( this.doc.createElement( 'br' ) );
                  }
                  subNode.nodeValue = rText.substring( 0, idx );
                }  
                else
                {
                  spanNode.insertBefore( this.doc.createTextNode( rText.substring( 0, idx ) ), subNode );
                  spanNode.insertBefore( this.doc.createElement( 'br' ), subNode );
                  subNode.nodeValue = rText.substring( idx+1 );
                }  
            }
          }
          subNode = subNode.nextSibling;
        }
        spanNode = spanNode.nextSibling;  
      }
    }
    else
    { // Html code
      var html = this.doc.body.innerHTML;
      html = html.gsub( String.fromCharCode(182), '<br/>' ); //'<br/>');'&#13;'
      this.doc.body.innerHTML = html;
    }
  },
  
  stub: function( event )
  {
    Event.stop( event );
    return false;
  }
}

var MyAjaxUpdater = Class.create();

Object.extend( Object.extend( MyAjaxUpdater.prototype, Ajax.Request.prototype ), 
{
  initialize: function( container, url, options ) 
  {
    this.element = container.doc.body;
    this.transport = Ajax.getTransport();
    this.setOptions( options );
    this.options.onSuccess = (function(transport, param) {
      this.updateContent();
    }).bind(this);

    this.request(url);
  },
  
  updateContent: function() 
  {
    this.element.innerHTML = this.transport.responseText;
  }
});
